﻿/************************************************************************/
/* FileName:        GCPen
 * Author:          Aric.W
 * Created:         2013/9/17 16:22:24
 * Version:         A001
 * Compiler:        Visual Studio 2010
 * Description:     
 * 
 * History:
 * <Author>         <Time>              <Version>   <Desc>
 * Aric.W    2013/9/17 16:22:24  A001        create
/************************************************************************/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Drawing2D;

namespace Common
{
    public struct GCPen
    {

        /// <summary>
        /// 颜色
        /// </summary>
        private GCColor color;

        public GCColor Color
        {
            get { return color; }
            set { color = value; }
        }

        /// <summary>
        /// 宽度
        /// </summary>
        private float width;

        public float Width
        {
            get { return width; }
            set { width = value; }
        }

        /// <summary>
        /// 线型
        /// </summary>
        private GCDashStyle dashStyle;

        public GCDashStyle DashStyle
        {
            get { return dashStyle; }
            set { dashStyle = value; }
        }

        /// <summary>
        /// 起始线帽样式
        /// </summary>
        private GCLineCapStyle startCapStyle;

        public GCLineCapStyle StartCapStyle
        {
            get { return startCapStyle; }
            set { startCapStyle = value; }
        }

        /// <summary>
        /// 结束线帽样式
        /// </summary>
        private GCLineCapStyle endCapStyle;

        public GCLineCapStyle EndCapStyle
        {
            get { return endCapStyle; }
            set { endCapStyle = value; }
        }

        /// <summary>
        /// 起始线帽大小
        /// </summary>
        private int startCapSize;

        public int StartCapSize
        {
            get { return startCapSize; }
            set { startCapSize = value; }
        }

        /// <summary>
        /// 结束线帽大小
        /// </summary>
        private int endCapSize;

        public int EndCapSize
        {
            get { return endCapSize; }
            set { endCapSize = value; }
        }

        /// <summary>
        /// 线条连接样式
        /// </summary>
        private GCLineJoinStyle lineJoin;

        public GCLineJoinStyle LineJoin
        {
            get { return lineJoin; }
            set { lineJoin = value; }
        }

        /// <summary>
        /// 自定义的虚线和空白区域的数组
        /// </summary>
        private float[] dashPattern;

        public float[] DashPattern
        {
            get { return dashPattern; }
            set { dashPattern = value; }
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="color">画笔颜色</param>
        public GCPen(GCColor color)
            : this(color, 1)
        {
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="color">画笔颜色</param>
        /// <param name="width">画笔宽度</param>
        public GCPen(GCColor color, float width)
            :this(color, width, GCDashStyle.Solid )
        {
        }

        private  GCPen(GCColor color, float width=1,GCDashStyle style = GCDashStyle.Solid,
            GCLineCapStyle startCapStyle = GCLineCapStyle.None, int startCapSize = 3,
            GCLineCapStyle endCapStyle = GCLineCapStyle.None, int endCapSize=3,
            GCLineJoinStyle joinStyle = GCLineJoinStyle.Miter, float[] dashPattern = null)
        {
            this.color = color;
            this.width = width;
            this.dashStyle = style;
            this.startCapStyle = startCapStyle;
            this.startCapSize = startCapSize;
            this.endCapStyle = endCapStyle;
            this.endCapSize = endCapSize;
            this.lineJoin = joinStyle;
            this.dashPattern = dashPattern;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public Pen GetPen()
        {
            Pen pen = new Pen(color.GetColor(), width);
            pen.DashStyle = (System.Drawing.Drawing2D.DashStyle)dashStyle;
            if (dashStyle == GCDashStyle.Custom)
            {
                pen.DashPattern = dashPattern;
            }
            if (startCapStyle != GCLineCapStyle.None)
            {
                pen.CustomStartCap = GetCustomCap(startCapStyle, StartCapSize, width);
            }
            if (endCapStyle != GCLineCapStyle.None)
            {
                pen.CustomEndCap = GetCustomCap(endCapStyle, endCapSize, width);
            }
            pen.LineJoin = (System.Drawing.Drawing2D.LineJoin)lineJoin;
            return pen;
        }

        /// <summary>
        /// 创建线帽
        /// </summary>
        /// <param name="capStyle">线帽样式</param>
        /// <param name="capSize">线帽尺寸</param>
        /// <param name="lineWidth">线宽</param>
        /// <returns></returns>
        public CustomLineCap GetCustomCap(GCLineCapStyle capStyle, int capSize, float lineWidth)
        {
            GraphicsPath path = new GraphicsPath();
            CustomLineCap lineCap = null;
            switch (capStyle)
            {
                case GCLineCapStyle.None:
                    break;
                case GCLineCapStyle.Arrow:
                    path.AddLines(new System.Drawing.PointF[] { 
                        new System.Drawing.PointF(-capSize, -capSize*2), 
                        new System.Drawing.PointF(0, 0),
                        new System.Drawing.PointF(capSize, -capSize*2) });
                    lineCap = new CustomLineCap(null, path);
                    break;
                case GCLineCapStyle.HollowTriangle:
                    path.AddLines(new System.Drawing.PointF[]
                    { 
                        new System.Drawing.PointF(-capSize, -capSize*2), 
                        new System.Drawing.PointF(0, 0),
                        new System.Drawing.PointF(capSize, -capSize*2),
                        new System.Drawing.PointF(-capSize, -capSize*2),
                        new System.Drawing.PointF(0, 0) 
                    });
                    lineCap = new CustomLineCap(null, path);
                    lineCap.BaseInset = capSize * 2;
                    break;
                case GCLineCapStyle.FilledTriangle:
                    path.AddLines(new System.Drawing.PointF[]
                    {
                        new System.Drawing.PointF(-capSize, -capSize*2),
                        new System.Drawing.PointF(0, 0),
                        new System.Drawing.PointF(capSize, -capSize*2),
                        new System.Drawing.PointF(-capSize, -capSize*2), 
                        new System.Drawing.PointF(0, 0)
                    });
                    lineCap = new CustomLineCap(path, null);
                    if (lineWidth <= 1.0)
                    {
                        lineCap.BaseInset = /*capSize * */4;
                    }
                    else
                    {
                        lineCap.BaseInset = capSize * 2;
                    }
                    break;
                case GCLineCapStyle.HollowCircle:
                    path.AddEllipse(new System.Drawing.Rectangle(-capSize, -capSize, 2 * capSize, 2 * capSize));
                    lineCap = new CustomLineCap(null, path);
                    lineCap.BaseInset = capSize;
                    break;
                case GCLineCapStyle.FilledCircle:
                    path.AddEllipse(new System.Drawing.Rectangle(-capSize, -capSize, 2 * capSize, 2 * capSize));
                    lineCap = new CustomLineCap(path, null);
                    lineCap.BaseInset = capSize - 1;
                    break;
                case GCLineCapStyle.HollowDiamond:
                    path.AddLines(new System.Drawing.PointF[] 
                    { 
                        new System.Drawing.PointF(-capSize, 0),
                        new System.Drawing.PointF(0,-capSize),
                        new System.Drawing.PointF(capSize, 0),
                        new System.Drawing.PointF(0, capSize),
                        new System.Drawing.PointF(-capSize, 0),
                        new System.Drawing.PointF(0,-capSize) 
                    });
                    lineCap = new CustomLineCap(null, path);
                    lineCap.BaseInset = capSize;
                    break;
                case GCLineCapStyle.FilledDiamond:
                    path.AddLines(new System.Drawing.PointF[]
                    {
                        new System.Drawing.PointF(-capSize, 0),
                        new System.Drawing.PointF(0,-capSize),
                        new System.Drawing.PointF(capSize, 0),
                        new System.Drawing.PointF(0, capSize),
                        new System.Drawing.PointF(-capSize, 0) ,
                        new System.Drawing.PointF(0,-capSize)
                    });
                    lineCap = new CustomLineCap(path, null);
                    lineCap.BaseInset = capSize - 1;
                    break;
                case GCLineCapStyle.HollowSquare:
                    path.AddRectangle(new System.Drawing.RectangleF(-capSize, -capSize, 2 * capSize, 2 * capSize));
                    lineCap = new CustomLineCap(null, path);
                    lineCap.BaseInset = capSize;
                    break;
                case GCLineCapStyle.FilledSquare:
                    path.AddRectangle(new System.Drawing.RectangleF(-capSize, -capSize, 2 * capSize, 2 * capSize));
                    lineCap = new CustomLineCap(path, null);
                    lineCap.BaseInset = capSize - 1;
                    break;
                default:
                    break;
            }
            return lineCap;
        }

    }//end GCPen
}
